package com.github.natholdallas.controller.admin

import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.github.natholdallas.common.*
import com.github.natholdallas.controller.PageIn
import com.github.natholdallas.controller.TinyUserSerializer
import com.github.natholdallas.database.*
import com.github.natholdallas.declaration.Attr
import com.github.natholdallas.declaration.Body
import com.github.natholdallas.declaration.Path
import org.springframework.data.domain.Page
import org.springframework.web.bind.annotation.*
import java.math.BigDecimal

@AViews
class AdminCtl(private val repo: Users) {

    @[GetMapping]
    fun list(@Attr page: PageIn): Page<User> {
        return repo.allByStaffOrAdmin(page)
    }

    @[GetMapping("/{id}")]
    fun retrieve(@Path id: Long): User {
        return repo.byId(id)
    }

    @[GetMapping("/me")]
    fun me(): User {
        return repo.byId(LOGINID)
    }

    @[PostMapping]
    fun create(@Body data: AdminIn) {
        repo.save(data)
        saveLog("[$USERNAME] 创建用户 $data")
    }

    @[PutMapping("/{id}")]
    fun update(@Path id: Long, @Body data: AdminIn) {
        repo.byIdThenUpdate(id, data)
        saveLog("[$USERNAME] 修改用户 $data")
    }

    @[DeleteMapping("/{id}")]
    fun destroy(@Path id: Long) {
        repo.deleteById(id)
        saveLog("[$USERNAME] 删除用户 $id")
    }

}


@AViews("/copilot")
class CopilotCtl(private val repo: Users) {

    @[GetMapping]
    fun list(@Attr page: PageIn): Page<User> {
        return repo.all(Role.COPILOT, page)
    }

    @[GetMapping("/tinylist") JsonSerialize(using = TinyUserSerializer::class)]
    fun tinylist(): List<User> {
        return repo.all(Role.COPILOT)
    }

    @[GetMapping("/{id}")]
    fun retrieve(@Path id: Long): User {
        return repo.byId(id)
    }

    @[PostMapping]
    fun create(@Body data: CopilotIn) {
        repo.save(data)
        saveLog("[$USERNAME] 新增陪玩 $data")
    }

    @[PutMapping("/{id}")]
    fun update(@Path id: Long, @Body data: CopilotIn) {
        repo.byIdThenUpdate(id, data)
        saveLog("[$USERNAME] 修改陪玩 $data")
    }

    @[DeleteMapping("/{id}")]
    fun destroy(@Path id: Long) {
        repo.deleteById(id)
        saveLog("[$USERNAME] 删除陪玩 $id")
    }

}

@AViews("/user")
class UserCtl(private val repo: Users) {

    @[GetMapping]
    fun list(@Attr page: PageIn): Page<User> {
        return repo.all(Role.USER, page)
    }

    @[GetMapping("/tinylist") JsonSerialize(using = TinyUserSerializer::class)]
    fun tinylist(): List<User> {
        return repo.all(Role.USER)
    }

    @[GetMapping("/{id}")]
    fun retrieve(@Path id: Long): User {
        return repo.byId(id)
    }

    @[PostMapping]
    fun create(@Body data: UserIn) {
        repo.save(data)
        saveLog("[$USERNAME] 新增老板 $data")
    }

    @[PutMapping("/{id}")]
    fun update(@Path id: Long, @Body data: UserIn) {
        repo.byIdThenUpdate(id, data)
        saveLog("[$USERNAME] 修改老板 $data")
    }

    @[DeleteMapping("/{id}")]
    fun destroy(@Path id: Long) {
        repo.deleteById(id)
        saveLog("[$USERNAME] 删除老板 $id")
    }

}


@AViews("/topup")
class TopupCtl(private val repo: Topups) {

    @[GetMapping]
    fun list(@Attr page: PageIn): Page<TopupTable> {
        return repo.all(page)
    }

    @[GetMapping("/{id}")]
    fun retrieve(@Path id: Long): TopupTable {
        return repo.byId(id)
    }

    @[PostMapping]
    fun create(@Body data: TopupIn) {
        repo.save(data)
        saveLog("[$USERNAME] 新增转账 $data")
    }

    @[PutMapping("/{id}")]
    fun update(@Path id: Long, @Body data: TopupIn) {
        repo.byIdThenUpdate(id, data) { isFalse(it.payment, "此订单已被标记归档") }
        saveLog("[$USERNAME] 修改转账 $data")
    }

    @[PatchMapping("/paid/{id}")]
    fun paid(@Path id: Long) {
        repo.byIdThenUpdate(id) {
            isFalse(it.payment, "此订单已被标记归档")
            it.payment = true
            it.user.amount += it.amount // 增加充值总数
            it.user.balance += it.amount + it.gift // 余额由当前余额加上充值金额和店铺福利
            it.amountRecord = it.user.amount
            it.balanceRecord = it.user.balance
        }
        saveLog("[$USERNAME] 归档充值订单 $id")
    }

    @[DeleteMapping("/{id}")]
    fun destroy(@Path id: Long) {
        repo.deleteById(id)
        saveLog("[$USERNAME] 删除转账 $id")
    }

}


@AViews("/order")
class OrderCtl(private val repo: Orders) {

    @[GetMapping]
    fun list(@Attr page: PageIn): Page<OrderTable> {
        return repo.all(page)
    }

    @[GetMapping("/{id}")]
    fun retrieve(@Path id: Long): OrderTable {
        return repo.byId(id)
    }

    @[PostMapping]
    fun create(@Body data: OrderIn) {
        repo.save(data)
        saveLog("[$USERNAME] 新增订单 $data")
    }

    @[PutMapping("/{id}")]
    fun update(@Path id: Long, @Body data: OrderIn): OrderTable {
        val order = repo.byIdThenUpdate(id, data)
        saveLog("[$USERNAME] 修改订单 $data")
        return order
    }

    @[PatchMapping("/paid/{id}")]
    fun paid(@Path id: Long) {
        repo.byIdThenUpdate(id) {
            isFalse(it.payment, "此订单已被标记归档")
            it.payment = true
            it.totalPrice = it.price * it.duration
            it.iPrice = BigDecimal(it.totalPrice) * BigDecimal("0.8")
            it.cPrice = BigDecimal(it.totalPrice) * BigDecimal("0.2")
            it.user.balance -= BigDecimal(it.totalPrice)
            it.amountRecord = it.user.amount
            it.balanceRecord = it.user.balance
        }
        saveLog("[$USERNAME] 归档充值订单 $id")
    }

    @[DeleteMapping("/{id}")]
    fun destroy(@Path id: Long) {
        repo.deleteById(id)
        saveLog("[$USERNAME] 删除订单记录 $id")
    }

}


@AViews("/log")
class LogCtl(private val repo: Logs) {

    @[GetMapping]
    fun list(@Attr page: PageIn): Page<String> {
        return repo.all(page) { it.msg }
    }

}
